module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Modify FSM and datapath from Fsm_serialdata
	parameter IDLE = 3'd0;
    parameter START = 3'd1;
    parameter DATA = 3'd2;
    parameter PARITY = 3'd3;
    parameter STOP = 3'd4;
    parameter WAIT = 3'd5;
    
    reg	[2:0]	state;
    reg	[2:0]	next_state;
    reg	[3:0]	data_cnt;
    reg	[7:0]	temp_in;
    reg			parity_reset;
    reg			parity_odd;
    
    always @(posedge clk) begin
        if(reset) begin
            state <= IDLE;
        end
        else begin
            state <= next_state;
        end
    end
    
    always @(*) begin
        case(state)
            IDLE:begin
                if(in) begin
                    next_state = IDLE;
                end
                else begin
                    next_state = START;
                end
            end
            START:next_state = DATA;
            DATA:begin
                if(data_cnt == 4'd8) begin
                    next_state = PARITY;
                end
                else begin
                    next_state = DATA;
                end
            end
            PARITY:begin
                if(in) begin
                    next_state = STOP;
                end
                else begin
                    next_state = WAIT;
                end
            end
            STOP:begin
                if(in) begin
                    next_state = IDLE;
                end
                else begin
                    next_state = START;
                end
            end
            WAIT:begin
                if(in) begin
                    next_state = IDLE;
                end
                else begin
                    next_state = WAIT;
                end
            end
        endcase
    end
    
    always @(posedge clk) begin
        if(reset) begin
            done <= 1'b0;
            out_byte <= 8'd0;
            data_cnt <= 4'd0;
        end
        else begin
            case(next_state) 
                IDLE:begin
                    done <= 1'b0;
                    out_byte <= 8'd0;
            		data_cnt <= 4'd0;
                end
                START:begin
                    done <= 1'b0;
                    out_byte <= 8'd0;
            		data_cnt <= 4'd0;
                end
                DATA:begin
                    data_cnt <= data_cnt + 1'b1;
                    temp_in[data_cnt] <= in;
                    done <= 1'b0;
                    out_byte <= 8'd0;
                end
                PARITY:begin
                    done <= 1'b0;
                    out_byte <= 8'd0;
            		data_cnt <= 4'd0;
                end
                STOP:begin
                    if(parity_odd) begin
                        done <= 1'b1;
                        out_byte <= temp_in;
                    end
                    else begin
                        done <= 1'b0;
                        out_byte <= 8'd0;
                    end
                end
                WAIT:begin
                    done <= 1'b0;
                    out_byte <= 8'd0;
                end
                default:begin
                    done <= 1'b0;
                    out_byte <= 8'd0;
            		data_cnt <= 4'd0;
                end
            endcase
        end
    end
    
    assign parity_reset = (reset || next_state == IDLE || next_state == START);
    
    parity u_parity_0(
        .clk(clk),
        .reset(parity_reset),
        .in(in),
        .odd(parity_odd)
    );

endmodule
